/**
 * 
 */
package co.edu.javeriana.ia.ga.readers;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;

import co.edu.javeriana.ia.ga.Descriptor;
import co.edu.javeriana.ia.ga.FrecuencyMapping;
import co.edu.javeriana.ia.ga.Genome;
import co.edu.javeriana.ia.ga.Secuence;

/**
 * <p>
 * Esta clases permite leer los datos de los datos de una secuencia
 * </p>
 * 
 * @author <a href="f.triana@javeriana.edu.co">Alejandro Triana</a>
 * @author <a href="rrios@javeriana.edu.co">Rafael Rios</a>
 * @version 1.0
 */
public class SecuenceReader {

	private static final String C_DESCRIPTOR = "C";
	private static final String G_DESCRIPTOR = "G";
	private static final String GC_DESCRIPTOR = "GC";
	public static final String TOKEN_SEPARATOR = ":";
	
	/**
	 * <p>
	 * Este metodo permite leer un conjunto de secuencias, dado un conjunto de archivos
	 * </p>
	 */
	public static List<Secuence> getSecuences(Map<String, Descriptor> mapDescriptor,
			Collection<File> files) {
		
		List<Secuence> lstSecuences = new ArrayList<Secuence>();
		
		for (File file : files) {
			lstSecuences.addAll(getSecuencesForFile(mapDescriptor, file));
		}
		
		return lstSecuences;
	}

	/**
	 * <p>
	 * Este metodo permite leer las secuencias de un archivo en especifico
	 * </p>
	 */
	public static List<Secuence> getSecuencesForFile(Map<String, Descriptor> mapDescriptor,
			File file) {

		try {
			
			LineIterator iter = FileUtils.lineIterator(file);
			List<Secuence> sequences = new ArrayList<Secuence>();

			while (iter.hasNext()) {
				
				Secuence secuence = new Secuence();
				
				Map<String, Descriptor> descriptors = new TreeMap<String, Descriptor>();
				String secuenceLine = (String) iter.next();
				
				String[] strDescriptor = secuenceLine.split("\t");
				Genome genome = getGenomeForSequenceFromToken(strDescriptor[0]);

				float gc = 0;

				for (int i = 1; i < strDescriptor.length; i++) {
					
					Descriptor itemDescriptor = new Descriptor();

					String valueDescriptor = strDescriptor[i]
							.split(TOKEN_SEPARATOR)[0];

					String frecuencyDescriptor = strDescriptor[i]
							.split(TOKEN_SEPARATOR)[1];

					if (!valueDescriptor.equals(G_DESCRIPTOR) && !valueDescriptor.equals(C_DESCRIPTOR)) {

						double frecCon = Double.parseDouble(frecuencyDescriptor);
						int frecDis = FrecuencyMapping.mapping(frecCon);

						itemDescriptor.setFrecuency(frecDis);
						itemDescriptor.setId(valueDescriptor);
						itemDescriptor.setInternalId(mapDescriptor.get(valueDescriptor).getInternalId());
						
						descriptors.put(itemDescriptor.getId(), itemDescriptor);
						
					} else {
						gc += Float.parseFloat(frecuencyDescriptor);
					}
				}
				
				Descriptor itemDescriptor = new Descriptor();
				itemDescriptor.setFrecuency(FrecuencyMapping.mapping(gc));
				itemDescriptor.setId(GC_DESCRIPTOR);
				itemDescriptor.setInternalId(mapDescriptor.get(GC_DESCRIPTOR).getInternalId());
				
				descriptors.put(itemDescriptor.getId(), itemDescriptor);
				
				secuence.setDescriptors(descriptors);
				secuence.setGenome(genome);
				sequences.add(secuence);
			}
			
			return sequences;

		} catch (IOException e) {
			throw new RuntimeException(
					"File Descriptors doesnt not exist or has a problem");
		}
	}
	
	/**
	 * <p>
	 * Permite retornar el genoma correspondiente a la secuencia, dado un token
	 * de la cadena de la secuencia
	 * </p>
	 */
	private static Genome getGenomeForSequenceFromToken(String token) {
		
		List<Genome> genomes = GenomeReader.instance.getGenomes();

		for (Genome genome : genomes) {
			if (token.contains(genome.getName())) {
				return genome;
			}
		}

		return null;
	}

}
